package routers

import (
	"fmt"
	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"io"
	"mygin/configs"
	handler "mygin/controllers/handlers"
	"mygin/filters"
	"mygin/routers/admin"
	"mygin/routers/general"
	"os"
	"time"
)

// 初始化所有自定义的路由配置, 并进行路由分组
func InitRouter() *gin.Engine {
	// 我要多看看http协议, Content-Type有哪些类型

	/*
		Gin框架的请求日志默认在控制台输出，但更多的时候，尤其上线运行时，我们希望将用户的请求日志保存到日志文件中，
		以便更好的分析与备份。通过gin.DefaultWriter变量可能控制日志的保存方式,默认是:
		var DefaultWriter io.Writer = os.Stdout
		也就是默认是控制台输出,并没有保存起来.那我们们可以根据如下操作创建一个log文件,并保存日志信息:
	*/
	fileName := configs.GetEnv().ROUTER_LOG_PATH
	file, _ := os.Create(fileName)
	//gin.DefaultWriter = file //gin.DefaultWriter = io.MultiWriter(file) 效果是一样的
	// 如果希望是控制台和日志文件都记录的话:
	gin.DefaultWriter = io.MultiWriter(file, os.Stdout) //同时保存到文件和在控制台中输出

	router := gin.New() // 创建路由对象, 无中间件
	// 或者使用gin.Default() 来创建包含了默认中间件logger and recovery (crash-free)的路由对象

	// 从路由中过滤掉静态文件的请求
	//router.LoadHTMLGlob(configs.GetEnv().TEMPLATE_PATH + "/*")

	//设置静态文件目录，如果访问localhost:8080/assets/test.txt
	//如果./assets/test.txt文件存在，那么就返回该文件，否则返回404
	router.Static("/static", "./frontend")
	//和上面的功能一样
	//generalRouter.StaticFS("/test.html", http.Dir("./frontend/templates/test.html"))

	// 性能分析工具, 暂时不懂
	if configs.GetEnv().DEBUG {
		pprof.Register(router)
	}

	router.Use(handler.HandleErrors())    // 自定义错误处理
	router.Use(filters.RegisterSession()) // 全局session
	router.Use(filters.RegisterCache())   // 全局cache

	//router.Use(auth.RegisterGlobalAuthDriver("cookie", "web_auth")) // 全局auth cookie
	//router.Use(auth.RegisterGlobalAuthDriver("jwt", "jwt_auth"))    // 全局auth jwt

	// 添加全局中间件: gin.Logger(), gin.Recovery(), Validate()
	router.Use(Validate()) //统一身份验证, 当然也可以在每个路由中单独添加此中间件.
	// 如果使用了gin.Default()就可以省略以下这两个步骤
	//router.Use(gin.Logger()) // 默认的日志功能, 下面我用了自定义日志格式
	router.Use(gin.Recovery()) // 默认的http请求错误恢复功能

	// 但是呢,默认的日志格式太SB,所以我们可以自定义日志格式:
	router.Use(gin.LoggerWithFormatter(func(param gin.LogFormatterParams) string {
		return fmt.Sprintf("%s - [%s] \"%s %s %s %d %s \"%s\" %s\"\n",
			param.ClientIP,
			param.TimeStamp.Format(time.RFC1123),
			param.Method,
			param.Path,
			param.Request.Proto,
			param.StatusCode,
			param.Latency,
			param.Request.UserAgent(),
			param.ErrorMessage,
		)
	}))

	// 静态资源路径配置：

	// 调用分组路由的配置
	admin.AdminApiRouter(router)
	general.GeneralApiRouter(router)

	return router
}

// 验证身份
func Validate() gin.HandlerFunc {
	return func(c *gin.Context) {
		/*//这一部分可以替换成从session/cookie中获取，
		username:=c.Query("username")
		password:=c.Query("password")

		if username=="ft" && password =="123"{
			c.JSON(http.StatusOK,gin.H{"message":"身份验证成功"})
			c.Next()  //该句可以省略，写出来只是表明可以进行验证下一步中间件，不写，也是内置会继续访问下一个中间件的
		}else {
			c.Abort()
			c.JSON(http.StatusUnauthorized,gin.H{"message":"身份验证失败"})
			return// return也是可以省略的，执行了abort操作，会内置在中间件defer前，return，写出来也只是解答为什么Abort()
			之后，还能执行返回JSON数据
		}*/
	}
}
